mod utils;

use clap::{Arg, ArgAction, Command};
use common::file_system::deserialize_toml;
use common::model::ProjectConfig;
use common::model::{NpmModuleInfo, ProjectDirInfo};
use common::util::vue3::{init_import, init_template};
use common::util::{init_project_api_json, run_gen_api, merge_api_json};
use std::fs;
use std::path::Path;
use utils::{run_install};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let matches = Command::new("project dependency installer")
        .version("1.0")
        .author("caozongying<zongying_cao@163.com>")
        .about(
            "caozongying_cao<zongying_cao@163.com> is the author of project dependency installer",
        )
        .arg(
            Arg::new("config")
                .short('c')
                .long("config")
                .value_name("CONFIG_FILE_PATH")
                .help("配置文件路径")
                .action(ArgAction::Set),
        )
        .arg(
            Arg::new("project_dir")
                .short('p')
                .long("project_dir")
                .value_name("PROJECT_DIR")
                .help("项目路径")
                .action(ArgAction::Set),
        )
        .get_matches();

    let config_file_path = Path::new(
        matches
            .get_one::<String>("config")
            .expect("无法获取config的文件路径"),
    );

    let project_dir = &matches
        .get_one::<String>("project_dir")
        .expect("无法获取project_dir");

    let project_config = deserialize_toml::<ProjectConfig>(&fs::read_to_string(config_file_path)?)?;
    if let Some(project_deps) = project_config.project_deps {
        let project_api_json_path = &init_project_api_json(Path::new(project_dir))?;

        let project_dir_info = ProjectDirInfo::new(Path::new(project_dir));

        let mut npm_modules: Vec<NpmModuleInfo> = vec![];

        for dep in project_deps {
            let npm_module_info =
                NpmModuleInfo::new_installed(Path::new(project_dir), &dep.name()?);
            npm_modules.push(npm_module_info.clone());

            run_install(&dep, Path::new(project_dir))?;
            merge_api_json(project_api_json_path, &npm_module_info)?;
            run_gen_api(config_file_path, Path::new(project_dir), project_api_json_path)?;
            init_import(&project_dir_info, &npm_module_info)?;
        }

        if let Some(composition) = project_config.composition {
            init_template(&project_dir_info, &npm_modules, &composition)?;
        }
    }

    Ok(())
}
